import {invoke} from "./invoke";

const HIJACK_EVENTS_NAME = /^(hashchange|popstate)$/i;
const EVENTS_POOL = {
  hashchange: [],
  popstate: []
};

// 路由改变会触发invoke
function reroute() {
  console.log('reroute arguments:',arguments);
  invoke([], arguments/*←*/);
}

// 先用原生的监听 reroute 后面的监听都会被拦截
// 确保是我们的router监听先执行
window.addEventListener('hashchange', reroute);
window.addEventListener('popstate', reroute);

// 拦截所有注册的事件,以便确保这里的事件总是第一个执行
const originalAddEventListener = window.addEventListener;
const originalRemoveEventListener = window.removeEventListener;
window.addEventListener = function (eventName, handler, args) {
  if (eventName && HIJACK_EVENTS_NAME.test(eventName) && typeof handler === 'function') {
    EVENTS_POOL[eventName].indexOf(handler) === -1 &&
    EVENTS_POOL[eventName].push(handler);
  } else{
    originalAddEventListener.apply(this, arguments);
  }
};

window.removeEventListener = function (eventName, handler) {
  if (eventName && HIJACK_EVENTS_NAME.test(eventName) && typeof handler === 'function') {
    let eventList = EVENTS_POOL[eventName];
    eventList.indexOf(handler) > -1 &&
    (EVENTS_POOL[eventName] = eventList.filter(fn => fn !== handler));
  }else {
    originalRemoveEventListener.apply(this, arguments);
  }
};


// 拦截history的方法,因为pushState和replaceState方法并不会触发onpopstate事件,所以我们即便在onpopstate时执行了reroute方法,也要在这里执行下reroute方法。
const originalHistoryPushState = window.history.pushState;
const originalHistoryReplaceState = window.history.replaceState;
window.history.pushState = function (state, title, url) {
  let result = originalHistoryPushState.apply(this, arguments);
  reroute(mockPopStateEvent(state));
  return result;
};
window.history.replaceState = function (state, title, url) {
  let result = originalHistoryReplaceState.apply(this, arguments);
  reroute(mockPopStateEvent(state));
  return result;
};

function mockPopStateEvent(state) {
  return new PopStateEvent('popstate', {state});
}

export function callCapturedEvents(eventArgs) {
  console.log('callCapturedEvents:',callCapturedEvents);
  console.log('eventArgs:',eventArgs);
  if (!eventArgs) {
    return;
  }
  if (!Array.isArray(eventArgs)) {
    eventArgs = [eventArgs];
  }
  const name = eventArgs[0].type;
  console.log('name:',name);
  if (!EVENTS_POOL[name] || EVENTS_POOL[name].length === 0) {
    return;
  }
  EVENTS_POOL[name].forEach(handler => handler.apply(window, eventArgs));
}
